package javaIo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * 事件驱动模型
 * Created by zzy on 2018/4/2.
 */
public class Nio {

    private Selector selector;

    public static void main(String[] args) throws Exception {
        Nio nio= (Nio) Class.forName("javaIo.Nio").newInstance();
        nio.initServer(12345);
        nio.listenSelector();
    }

    public void initServer(int port) throws IOException{
        //服务端通道，相当于传统的ServerSocket
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
        //设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        //绑定端口
        serverSocketChannel.socket().bind(new InetSocketAddress(port));
        //获得通道管理器
        this.selector=Selector.open();
        //将通道管理器和通道绑定，并为通道注册SelectionKey,OP_ACCEPT事件，注册事件后，
        //当该时间到达时，selector.select()会返回，如果该事件没到达selector.select()会一直阻塞，
        //通过selector管理是否有accpet事件
        serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务启动成功。。。端口为："+port);
    }

    public void listenSelector() throws IOException{
        while (true){
            //等待时间到来
            this.selector.select();
            Iterator<?> iteratorKey=this.selector.selectedKeys().iterator();
            while (iteratorKey.hasNext()){
                //取出时间
                SelectionKey selectionKey= (SelectionKey) iteratorKey.next();
                iteratorKey.remove();
                handler(selectionKey);
            }
        }
    }

    private void handler(SelectionKey selectionKey) throws IOException {
        if(selectionKey.isAcceptable()){//处理客户端连接请求事件
            System.out.println("新的客户端连接。。。");
            ServerSocketChannel server= (ServerSocketChannel) selectionKey.channel();
            SocketChannel channel=server.accept();
            //设置成非阻塞
            channel.configureBlocking(false);
            channel.register(this.selector,SelectionKey.OP_READ);


        }else if(selectionKey.isReadable()){//处理读事件
            SocketChannel channel= (SocketChannel) selectionKey.channel();
            //创建读取的缓冲区
            ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
            int readData=channel.read(byteBuffer);
            if(readData>0){
                String msg=new String(byteBuffer.array(),"GBK").trim();
                System.out.println("服务端接收到"+msg);
                //回写数据
                ByteBuffer writeBackBuffer=ByteBuffer.wrap("receive data".getBytes("GBK"));
                channel.write(writeBackBuffer);
            }

        }
    }
}
